#ifndef _BASETHREAD_H
#define _BASETHREAD_H

#include <list>
#include <stdio.h>

#include "basetype.h"
#include "threadlib.h"

using namespace std;
using namespace TypesLib;

namespace ThreadLib
{

template<bool USELIST, typename _ElementType, int SIZE>
class TheadMessagePoll
{
public:
    typedef _ElementType    ElementType;
public:
    ElementType*    getPtrElement()
    {
        ElementType*    Ret = NULL;
        m_pollMutex.lock();
        Ret = m_poll.getPtrElement();
        m_pollMutex.unLock();
        return Ret;
    }

    void            freePtrElement(ElementType* pPtr)
    {
        m_pollMutex.lock();
        m_poll.freePtrElement(pPtr);
        m_pollMutex.unLock();
    }

    void            pushUsed(ElementType* pPtr)
    {
        m_recvListMutex.lock();
        m_recvList.push_back(pPtr);
        m_recvListMutex.unLock();
    }

    list<ElementType*>&            makeCopyList()
    {
        m_recvListMutex.lock();
        std::copy(m_recvList.begin(), m_recvList.end(), std::back_inserter(m_copyList));
        m_recvList.clear();
        m_recvListMutex.unLock();

        return    m_copyList;
    }

    bool    isEmpty()
    {
        return m_recvList.empty();
    }
private:
    ThreadLib::Mutex                                m_pollMutex;
    TypePool<ElementType, USELIST>            m_poll;

    ThreadLib::Mutex                                m_recvListMutex;
    list<ElementType*>                                m_recvList;
    list<ElementType*>                                m_copyList;
};

class AbstractThread
{
public:
    AbstractThread();
    virtual                    ~AbstractThread();
    virtual void            StartThread()
    {
        m_threadID = ThreadLib::Create(AbstractThread::ThreadFunction, this);
    }
    ThreadLib::ThreadID        getThreadID()
    {
        return m_threadID;
    }
    virtual void            Run() = 0;
    static void                ThreadFunction(void*    pThread)
    {
        AbstractThread* pThis = (AbstractThread*)pThread;
        pThis->Run();
    }

protected:
    ThreadLib::ThreadID m_threadID;
};

#define THREAD_TYPE_MAX 0xFF
class ThreadManage : public Singleton<ThreadManage>
{
private:
    ThreadManage();
public:
    void    registerThread(int   aType, AbstractThread* pThread);
    AbstractThread*    getThreadOfType(int   pType);
private:
    AbstractThread*        g_threadArray[THREAD_TYPE_MAX];
    ThreadLib::Mutex    g_threadRegisterMutex;
};

template<typename _MESSAGETYPE, int MESSAGESIZE>
class MessageThread : public AbstractThread
{
public:
    typedef    _MESSAGETYPE    MESSAGETYPE;
    typedef TheadMessagePoll<false, MESSAGETYPE,MESSAGESIZE> MYPOLLTYPE;
    typedef typename MYPOLLTYPE::ElementType    ELEMENT;
    typedef ELEMENT*    PTR_ELEMENT;

public:
    MessageThread()
    {
        m_threadID = NULL;
    }
    ~MessageThread()
    {

    }
    void    startThread()
    {
        if (NULL != m_threadID)
        {
            return;
        }
        AbstractThread::StartThread();
    }

    void                writeMessage(MESSAGETYPE* pMessage)
    {
        m_messagePoll.pushUsed(pMessage);
    }
    MESSAGETYPE*  getMessage()
    {
        return m_messagePoll.getPtrElement();
    }
    void        freeMessage(MESSAGETYPE* pPtr)
    {
        m_messagePoll.freePtrElement(pPtr);
    }
    inline  int     getType()
    {
        return m_type;
    }
    inline void    setType(int aType)
    {
        m_type = aType;
        if(NULL != m_threadID)
        {
            ThreadManage* retManage = ThreadManage::GetInstance();
            if(NULL != retManage)
            {
                retManage->registerThread(m_type, this);
            }
        }
    }

protected:
    int                                                                m_type;
    TheadMessagePoll<false, MESSAGETYPE,MESSAGESIZE>                m_messagePoll;
};

}

#endif
